<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen 1.8.14"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>FabGL: VGA/SpaceInvaders/SpaceInvaders.ino</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="navtree.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="resize.js"></script>
<script type="text/javascript" src="navtreedata.js"></script>
<script type="text/javascript" src="navtree.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
  $(document).ready(initResizable);
/* @license-end */</script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr style="height: 56px;">
  <td id="projectalign" style="padding-left: 0.5em;">
   <div id="projectname">FabGL
   </div>
   <div id="projectbrief">ESP32 Display Controller and Graphics Library</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.8.14 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
var searchBox = new SearchBox("searchBox", "search",false,'Search');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */</script>
<div id="main-nav"></div>
</div><!-- top -->
<div id="side-nav" class="ui-resizable side-nav-resizable">
  <div id="nav-tree">
    <div id="nav-tree-contents">
      <div id="nav-sync" class="sync"></div>
    </div>
  </div>
  <div id="splitbar" style="-moz-user-select:none;" 
       class="ui-resizable-handle">
  </div>
</div>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:cf05388f2679ee054f2beb29a391d25f4e673ac3&amp;dn=gpl-2.0.txt GPL-v2 */
$(document).ready(function(){initNavTree('_v_g_a_2_space_invaders_2_space_invaders_8ino-example.html','');});
/* @license-end */
</script>
<div id="doc-content">
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div class="header">
  <div class="headertitle">
<div class="title">VGA/SpaceInvaders/SpaceInvaders.ino</div>  </div>
</div><!--header-->
<div class="contents">
<p>Space invaders full game</p>
<div class="fragment"><div class="line"><span class="comment">/*</span></div><div class="line"><span class="comment">  Created by Fabrizio Di Vittorio (fdivitto2013@gmail.com) - www.fabgl.com</span></div><div class="line"><span class="comment">  Copyright (c) 2019-2020 Fabrizio Di Vittorio.</span></div><div class="line"><span class="comment">  All rights reserved.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">  This file is part of FabGL Library.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">  FabGL is free software: you can redistribute it and/or modify</span></div><div class="line"><span class="comment">  it under the terms of the GNU General Public License as published by</span></div><div class="line"><span class="comment">  the Free Software Foundation, either version 3 of the License, or</span></div><div class="line"><span class="comment">  (at your option) any later version.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">  FabGL is distributed in the hope that it will be useful,</span></div><div class="line"><span class="comment">  but WITHOUT ANY WARRANTY; without even the implied warranty of</span></div><div class="line"><span class="comment">  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span></div><div class="line"><span class="comment">  GNU General Public License for more details.</span></div><div class="line"><span class="comment"></span></div><div class="line"><span class="comment">  You should have received a copy of the GNU General Public License</span></div><div class="line"><span class="comment">  along with FabGL.  If not, see &lt;http://www.gnu.org/licenses/&gt;.</span></div><div class="line"><span class="comment"> */</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="fabgl_8h.html">fabgl.h</a>&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;<a class="code" href="fabutils_8h.html">fabutils.h</a>&quot;</span></div><div class="line"></div><div class="line"><span class="preprocessor">#include &quot;sprites.h&quot;</span></div><div class="line"><span class="preprocessor">#include &quot;sounds.h&quot;</span></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">using</span> fabgl::iclamp;</div><div class="line"></div><div class="line"></div><div class="line"><a name="_a0"></a><a class="code" href="classfabgl_1_1_v_g_a_controller.html">fabgl::VGAController</a> DisplayController;</div><div class="line"><a name="_a1"></a><a class="code" href="classfabgl_1_1_canvas.html">fabgl::Canvas</a>        canvas(&amp;DisplayController);</div><div class="line"><a name="_a2"></a><a class="code" href="classfabgl_1_1_p_s2_controller.html">fabgl::PS2Controller</a> PS2Controller;</div><div class="line">SoundGenerator       soundGenerator;</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">// IntroScene</span></div><div class="line"></div><div class="line"><span class="keyword">struct </span>IntroScene : <span class="keyword">public</span> Scene {</div><div class="line"></div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> TEXTROWS = 4;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> TEXT_X   = 130;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> TEXT_Y   = 122;</div><div class="line"></div><div class="line">  <span class="keyword">static</span> <span class="keywordtype">int</span> controller_; <span class="comment">// 1 = keyboard, 2 = mouse</span></div><div class="line"></div><div class="line">  <span class="keywordtype">int</span> textRow_  = 0;</div><div class="line">  <span class="keywordtype">int</span> textCol_  = 0;</div><div class="line">  <span class="keywordtype">int</span> starting_ = 0;</div><div class="line"></div><div class="line">  SamplesGenerator * music_ = <span class="keyword">nullptr</span>;</div><div class="line"></div><div class="line">  IntroScene()</div><div class="line">    : Scene(0, 20, DisplayController.getViewPortWidth(), DisplayController.getViewPortHeight())</div><div class="line">  {</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> init()</div><div class="line">  {</div><div class="line">    canvas.setBrushColor(<a name="a3"></a><a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cac1e9bce8242f443c54c7405223d616cd">Color::Black</a>);</div><div class="line">    canvas.clear();</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a name="a4"></a><a class="code" href="displaycontroller_8h_a4054936031229707e9189e4f2c865e67.html#a4054936031229707e9189e4f2c865e67">FillBackground</a>(<span class="keyword">true</span>));</div><div class="line">    canvas.selectFont(&amp;fabgl::FONT_8x8);</div><div class="line">    canvas.setPenColor(<a name="a5"></a><a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1ca3bec3eb0c8a4aab8e31a3a290493ab85">Color::BrightWhite</a>);</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a name="a6"></a><a class="code" href="displaycontroller_8h_aceea3df50e577272aa576027eede649d.html#aceea3df50e577272aa576027eede649d">DoubleWidth</a>(1));</div><div class="line">    canvas.drawText(50, 15, <span class="stringliteral">&quot;SPACE INVADERS&quot;</span>);</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a class="code" href="displaycontroller_8h_aceea3df50e577272aa576027eede649d.html#aceea3df50e577272aa576027eede649d">DoubleWidth</a>(0));</div><div class="line"></div><div class="line">    canvas.setPenColor(<a name="a7"></a><a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cad0784a3f969fe736e8b271a5a161d106">Color::Green</a>);</div><div class="line">    canvas.drawText(10, 40, <span class="stringliteral">&quot;ESP32 version by Fabrizio Di Vittorio&quot;</span>);</div><div class="line">    canvas.drawText(105, 55, <span class="stringliteral">&quot;www.fabgl.com&quot;</span>);</div><div class="line"></div><div class="line">    canvas.setPenColor(<a name="a8"></a><a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cabf28513245738599d13e3ce36bd16c82">Color::Yellow</a>);</div><div class="line">    canvas.drawText(72, 97, <span class="stringliteral">&quot;* SCORE ADVANCE TABLE *&quot;</span>);</div><div class="line">    canvas.drawBitmap(TEXT_X - 20 - 2, TEXT_Y, &amp;bmpEnemyD);</div><div class="line">    canvas.drawBitmap(TEXT_X - 20, TEXT_Y + 15, &amp;bmpEnemyA[0]);</div><div class="line">    canvas.drawBitmap(TEXT_X - 20, TEXT_Y + 30, &amp;bmpEnemyB[0]);</div><div class="line">    canvas.drawBitmap(TEXT_X - 20, TEXT_Y + 45, &amp;bmpEnemyC[0]);</div><div class="line"></div><div class="line">    canvas.setBrushColor(<a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cac1e9bce8242f443c54c7405223d616cd">Color::Black</a>);</div><div class="line"></div><div class="line">    controller_ = 0;</div><div class="line"></div><div class="line">    music_ = soundGenerator.playSamples(themeSoundSamples, <span class="keyword">sizeof</span>(themeSoundSamples), 100, -1);</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> update(<span class="keywordtype">int</span> updateCount)</div><div class="line">  {</div><div class="line">    <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">char</span> * scoreText[] = {<span class="stringliteral">&quot;= ? MISTERY&quot;</span>, <span class="stringliteral">&quot;= 30 POINTS&quot;</span>, <span class="stringliteral">&quot;= 20 POINTS&quot;</span>, <span class="stringliteral">&quot;= 10 POINTS&quot;</span> };</div><div class="line"></div><div class="line">    <span class="keyword">auto</span> keyboard = PS2Controller.<a name="a9"></a><a class="code" href="classfabgl_1_1_p_s2_controller_ab7bbbedef758e471e6eb693acfb17c33.html#ab7bbbedef758e471e6eb693acfb17c33">keyboard</a>();</div><div class="line">    <span class="keyword">auto</span> mouse    = PS2Controller.<a name="a10"></a><a class="code" href="classfabgl_1_1_p_s2_controller_a2248eef1cd0e3b15957c08d6094926b6.html#a2248eef1cd0e3b15957c08d6094926b6">mouse</a>();</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (starting_) {</div><div class="line"></div><div class="line">      <span class="keywordflow">if</span> (starting_ &gt; 50) {</div><div class="line">        <span class="comment">// stop music</span></div><div class="line">        soundGenerator.detach(music_);</div><div class="line">        <span class="comment">// stop scene</span></div><div class="line">        stop();</div><div class="line">      }</div><div class="line"></div><div class="line">      ++starting_;</div><div class="line">      canvas.scroll(0, -5);</div><div class="line"></div><div class="line">    } <span class="keywordflow">else</span> {</div><div class="line">      <span class="keywordflow">if</span> (updateCount &gt; 30 &amp;&amp; updateCount % 5 == 0 &amp;&amp; textRow_ &lt; 4) {</div><div class="line">        <span class="keywordtype">int</span> x = TEXT_X + textCol_ * canvas.getFontInfo()-&gt;width;</div><div class="line">        <span class="keywordtype">int</span> y = TEXT_Y + textRow_ * 15 - 4;</div><div class="line">        canvas.setPenColor(<a name="a11"></a><a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cab548046646b36c12aa6ba841de500094">Color::White</a>);</div><div class="line">        canvas.drawChar(x, y, scoreText[textRow_][textCol_]);</div><div class="line">        ++textCol_;</div><div class="line">        <span class="keywordflow">if</span> (scoreText[textRow_][textCol_] == 0) {</div><div class="line">          textCol_ = 0;</div><div class="line">          ++textRow_;</div><div class="line">        }</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keywordflow">if</span> (updateCount % 20 == 0) {</div><div class="line">        canvas.setPenColor(random(256), random(256), random(256));</div><div class="line">        <span class="keywordflow">if</span> (keyboard-&gt;isKeyboardAvailable() &amp;&amp; mouse-&gt;isMouseAvailable())</div><div class="line">          canvas.drawText(45, 75, <span class="stringliteral">&quot;Press [SPACE] or CLICK to Play&quot;</span>);</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span> (keyboard-&gt;isKeyboardAvailable())</div><div class="line">          canvas.drawText(80, 75, <span class="stringliteral">&quot;Press [SPACE] to Play&quot;</span>);</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span> (mouse-&gt;isMouseAvailable())</div><div class="line">          canvas.drawText(105, 75, <span class="stringliteral">&quot;Click to Play&quot;</span>);</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// handle keyboard or mouse (after two seconds)</span></div><div class="line">      <span class="keywordflow">if</span> (updateCount &gt; 50) {</div><div class="line">        <span class="keywordflow">if</span> (keyboard-&gt;isKeyboardAvailable() &amp;&amp; keyboard-&gt;isVKDown(<a name="a12"></a><a class="code" href="group___enumerations_gad0e6e31d5953384be4ea987eb3923e02.html#ggad0e6e31d5953384be4ea987eb3923e02a3c7529306367d92950b980963dabe2b0">fabgl::VK_SPACE</a>))</div><div class="line">          controller_ = 1;  <span class="comment">// select keyboard as controller</span></div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span> (mouse-&gt;isMouseAvailable() &amp;&amp; mouse-&gt;deltaAvailable() &amp;&amp; mouse-&gt;getNextDelta(<span class="keyword">nullptr</span>, 0) &amp;&amp; mouse-&gt;status().buttons.left)</div><div class="line">          controller_ = 2;  <span class="comment">// select mouse as controller</span></div><div class="line">        starting_ = (controller_ &gt; 0);  <span class="comment">// start only when a controller has been selected</span></div><div class="line">      }</div><div class="line">    }</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> collisionDetected(Sprite * spriteA, Sprite * spriteB, Point collisionPoint)</div><div class="line">  {</div><div class="line">  }</div><div class="line"></div><div class="line">};</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">int</span> IntroScene::controller_ = 0;</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">// GameScene</span></div><div class="line"></div><div class="line"></div><div class="line"><span class="keyword">struct </span>GameScene : <span class="keyword">public</span> Scene {</div><div class="line"></div><div class="line">  <span class="keyword">enum</span> SpriteType { TYPE_PLAYERFIRE, TYPE_ENEMIESFIRE, TYPE_ENEMY, TYPE_PLAYER, TYPE_SHIELD, TYPE_ENEMYMOTHER };</div><div class="line"></div><div class="line">  <span class="keyword">struct </span>SISprite : Sprite {</div><div class="line">    SpriteType type;</div><div class="line">    uint8_t    enemyPoints;</div><div class="line">  };</div><div class="line"></div><div class="line">  <span class="keyword">enum</span> GameState { GAMESTATE_PLAYING, GAMESTATE_PLAYERKILLED, GAMESTATE_ENDGAME, GAMESTATE_GAMEOVER, GAMESTATE_LEVELCHANGING, GAMESTATE_LEVELCHANGED };</div><div class="line"></div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> PLAYERSCOUNT       = 1;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> SHIELDSCOUNT       = 4;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ROWENEMIESCOUNT    = 11;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> PLAYERFIRECOUNT    = 1;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIESFIRECOUNT   = 1;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMYMOTHERCOUNT   = 1;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> SPRITESCOUNT       = PLAYERSCOUNT + SHIELDSCOUNT + 5 * ROWENEMIESCOUNT + PLAYERFIRECOUNT + ENEMIESFIRECOUNT + ENEMYMOTHERCOUNT;</div><div class="line"></div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIES_X_SPACE    = 16;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIES_Y_SPACE    = 10;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIES_START_X    = 0;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIES_START_Y    = 30;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIES_STEP_X     = 6;</div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> ENEMIES_STEP_Y     = 8;</div><div class="line"></div><div class="line">  <span class="keyword">static</span> <span class="keyword">const</span> <span class="keywordtype">int</span> PLAYER_Y           = 170;</div><div class="line"></div><div class="line">  <span class="keyword">static</span> <span class="keywordtype">int</span> lives_;</div><div class="line">  <span class="keyword">static</span> <span class="keywordtype">int</span> score_;</div><div class="line">  <span class="keyword">static</span> <span class="keywordtype">int</span> level_;</div><div class="line">  <span class="keyword">static</span> <span class="keywordtype">int</span> hiScore_;</div><div class="line"></div><div class="line">  SISprite * sprites_     = <span class="keyword">new</span> SISprite[SPRITESCOUNT];</div><div class="line">  SISprite * player_      = sprites_;</div><div class="line">  SISprite * shields_     = player_ + PLAYERSCOUNT;</div><div class="line">  SISprite * enemies_     = shields_ + SHIELDSCOUNT;</div><div class="line">  SISprite * enemiesR1_   = enemies_;</div><div class="line">  SISprite * enemiesR2_   = enemiesR1_ + ROWENEMIESCOUNT;</div><div class="line">  SISprite * enemiesR3_   = enemiesR2_ + ROWENEMIESCOUNT;</div><div class="line">  SISprite * enemiesR4_   = enemiesR3_ + ROWENEMIESCOUNT;</div><div class="line">  SISprite * enemiesR5_   = enemiesR4_ + ROWENEMIESCOUNT;</div><div class="line">  SISprite * playerFire_  = enemiesR5_ + ROWENEMIESCOUNT;</div><div class="line">  SISprite * enemiesFire_ = playerFire_ + PLAYERFIRECOUNT;</div><div class="line">  SISprite * enemyMother_ = enemiesFire_ + ENEMIESFIRECOUNT;</div><div class="line"></div><div class="line">  <span class="keywordtype">int</span> playerVelX_          = 0;  <span class="comment">// used when controller is keyboard (0 = no move)</span></div><div class="line">  <span class="keywordtype">int</span> playerAbsX_          = -1; <span class="comment">// used when controller is mouse (-1 = no move)</span></div><div class="line">  <span class="keywordtype">int</span> enemiesX_            = ENEMIES_START_X;</div><div class="line">  <span class="keywordtype">int</span> enemiesY_            = ENEMIES_START_Y;</div><div class="line"></div><div class="line">  <span class="comment">// enemiesDir_</span></div><div class="line">  <span class="comment">//   bit 0 : if 1 moving left</span></div><div class="line">  <span class="comment">//   bit 1 : if 1 moving right</span></div><div class="line">  <span class="comment">//   bit 2 : if 1 moving down</span></div><div class="line">  <span class="comment">//   bit 3 : if 0 before was moving left, if 1 before was moving right</span></div><div class="line">  <span class="comment">// Allowed cases:</span></div><div class="line">  <span class="comment">//   1  = moving left</span></div><div class="line">  <span class="comment">//   2  = moving right</span></div><div class="line">  <span class="comment">//   4  = moving down (before was moving left)</span></div><div class="line">  <span class="comment">//   12 = moving down (before was moving right)</span></div><div class="line"></div><div class="line">  <span class="keyword">static</span> constexpr <span class="keywordtype">int</span> ENEMY_MOV_LEFT              = 1;</div><div class="line">  <span class="keyword">static</span> constexpr <span class="keywordtype">int</span> ENEMY_MOV_RIGHT             = 2;</div><div class="line">  <span class="keyword">static</span> constexpr <span class="keywordtype">int</span> ENEMY_MOV_DOWN_BEFORE_LEFT  = 4;</div><div class="line">  <span class="keyword">static</span> constexpr <span class="keywordtype">int</span> ENEMY_MOV_DOWN_BEFORE_RIGHT = 12;</div><div class="line"></div><div class="line">  <span class="keywordtype">int</span> enemiesDir_          = ENEMY_MOV_RIGHT;</div><div class="line"></div><div class="line">  <span class="keywordtype">int</span> enemiesAlive_        = ROWENEMIESCOUNT * 5;</div><div class="line">  <span class="keywordtype">int</span> enemiesSoundCount_   = 0;</div><div class="line">  SISprite * lastHitEnemy_ = <span class="keyword">nullptr</span>;</div><div class="line">  GameState gameState_     = GAMESTATE_PLAYING;</div><div class="line"></div><div class="line">  <span class="keywordtype">bool</span> updateScore_        = <span class="keyword">true</span>;</div><div class="line">  int64_t pauseStart_;</div><div class="line"></div><div class="line">  Bitmap bmpShield[4] = { Bitmap(22, 16, shield_data, PixelFormat::Mask, RGB888(0, 255, 0), <span class="keyword">true</span>),</div><div class="line">                          Bitmap(22, 16, shield_data, PixelFormat::Mask, RGB888(0, 255, 0), <span class="keyword">true</span>),</div><div class="line">                          Bitmap(22, 16, shield_data, PixelFormat::Mask, RGB888(0, 255, 0), <span class="keyword">true</span>),</div><div class="line">                          Bitmap(22, 16, shield_data, PixelFormat::Mask, RGB888(0, 255, 0), <span class="keyword">true</span>), };</div><div class="line"></div><div class="line">  GameScene()</div><div class="line">    : Scene(SPRITESCOUNT, 20, DisplayController.getViewPortWidth(), DisplayController.getViewPortHeight())</div><div class="line">  {</div><div class="line">  }</div><div class="line"></div><div class="line">  ~GameScene()</div><div class="line">  {</div><div class="line">    <span class="keyword">delete</span> [] sprites_;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> initEnemy(Sprite * sprite, <span class="keywordtype">int</span> points)</div><div class="line">  {</div><div class="line">    SISprite * s = (SISprite*) sprite;</div><div class="line">    s-&gt;addBitmap(&amp;bmpEnemyExplosion);</div><div class="line">    s-&gt;type = TYPE_ENEMY;</div><div class="line">    s-&gt;enemyPoints = points;</div><div class="line">    addSprite(s);</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> init()</div><div class="line">  {</div><div class="line">    <span class="comment">// setup player</span></div><div class="line">    player_-&gt;addBitmap(&amp;bmpPlayer)-&gt;addBitmap(&amp;bmpPlayerExplosion[0])-&gt;addBitmap(&amp;bmpPlayerExplosion[1]);</div><div class="line">    player_-&gt;moveTo(152, PLAYER_Y);</div><div class="line">    player_-&gt;type = TYPE_PLAYER;</div><div class="line">    addSprite(player_);</div><div class="line">    <span class="comment">// setup player fire</span></div><div class="line">    playerFire_-&gt;addBitmap(&amp;bmpPlayerFire);</div><div class="line">    playerFire_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">    playerFire_-&gt;type = TYPE_PLAYERFIRE;</div><div class="line">    addSprite(playerFire_);</div><div class="line">    <span class="comment">// setup shields</span></div><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; 4; ++i) {</div><div class="line">      shields_[i].addBitmap(&amp;bmpShield[i])-&gt;moveTo(35 + i * 75, 150);</div><div class="line">      shields_[i].isStatic = <span class="keyword">true</span>;</div><div class="line">      shields_[i].type = TYPE_SHIELD;</div><div class="line">      addSprite(&amp;shields_[i]);</div><div class="line">    }</div><div class="line">    <span class="comment">// setup enemies</span></div><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; ROWENEMIESCOUNT; ++i) {</div><div class="line">      initEnemy( enemiesR1_[i].addBitmap(&amp;bmpEnemyA[0])-&gt;addBitmap(&amp;bmpEnemyA[1]), 30 );</div><div class="line">      initEnemy( enemiesR2_[i].addBitmap(&amp;bmpEnemyB[0])-&gt;addBitmap(&amp;bmpEnemyB[1]), 20 );</div><div class="line">      initEnemy( enemiesR3_[i].addBitmap(&amp;bmpEnemyB[0])-&gt;addBitmap(&amp;bmpEnemyB[1]), 20 );</div><div class="line">      initEnemy( enemiesR4_[i].addBitmap(&amp;bmpEnemyC[0])-&gt;addBitmap(&amp;bmpEnemyC[1]), 10 );</div><div class="line">      initEnemy( enemiesR5_[i].addBitmap(&amp;bmpEnemyC[0])-&gt;addBitmap(&amp;bmpEnemyC[1]), 10 );</div><div class="line">    }</div><div class="line">    <span class="comment">// setup enemies fire</span></div><div class="line">    enemiesFire_-&gt;addBitmap(&amp;bmpEnemiesFire[0])-&gt;addBitmap(&amp;bmpEnemiesFire[1]);</div><div class="line">    enemiesFire_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">    enemiesFire_-&gt;type = TYPE_ENEMIESFIRE;</div><div class="line">    addSprite(enemiesFire_);</div><div class="line">    <span class="comment">// setup enemy mother ship</span></div><div class="line">    enemyMother_-&gt;addBitmap(&amp;bmpEnemyD)-&gt;addBitmap(&amp;bmpEnemyExplosionRed);</div><div class="line">    enemyMother_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">    enemyMother_-&gt;type = TYPE_ENEMYMOTHER;</div><div class="line">    enemyMother_-&gt;enemyPoints = 100;</div><div class="line">    enemyMother_-&gt;moveTo(getWidth(), ENEMIES_START_Y);</div><div class="line">    addSprite(enemyMother_);</div><div class="line"></div><div class="line">    DisplayController.<a name="a13"></a><a class="code" href="classfabgl_1_1_bitmapped_display_controller_a75ba732cc6ae90f53757b588f6c75d7e.html#a75ba732cc6ae90f53757b588f6c75d7e">setSprites</a>(sprites_, SPRITESCOUNT);</div><div class="line"></div><div class="line">    canvas.setBrushColor(<a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cac1e9bce8242f443c54c7405223d616cd">Color::Black</a>);</div><div class="line">    canvas.clear();</div><div class="line"></div><div class="line">    canvas.setPenColor(<a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cad0784a3f969fe736e8b271a5a161d106">Color::Green</a>);</div><div class="line">    canvas.drawLine(0, 180, 320, 180);</div><div class="line"></div><div class="line">    <span class="comment">//canvas.setPenColor(Color::Yellow);</span></div><div class="line">    <span class="comment">//canvas.drawRectangle(0, 0, getWidth() - 1, getHeight() - 1);</span></div><div class="line"></div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a class="code" href="displaycontroller_8h_a4054936031229707e9189e4f2c865e67.html#a4054936031229707e9189e4f2c865e67">FillBackground</a>(<span class="keyword">true</span>));</div><div class="line">    canvas.selectFont(&amp;fabgl::FONT_4x6);</div><div class="line">    canvas.setPenColor(<a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cab548046646b36c12aa6ba841de500094">Color::White</a>);</div><div class="line">    canvas.drawText(125, 20, <span class="stringliteral">&quot;WE COME IN PEACE&quot;</span>);</div><div class="line">    canvas.selectFont(&amp;fabgl::FONT_8x8);</div><div class="line">    canvas.setPenColor(0, 255, 255);</div><div class="line">    canvas.drawText(2, 2, <span class="stringliteral">&quot;SCORE&quot;</span>);</div><div class="line">    canvas.setPenColor(0, 0, 255);</div><div class="line">    canvas.drawText(254, 2, <span class="stringliteral">&quot;HI-SCORE&quot;</span>);</div><div class="line">    canvas.setPenColor(255, 255, 255);</div><div class="line">    canvas.drawTextFmt(254, 181, <span class="stringliteral">&quot;Level %02d&quot;</span>, level_);</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (IntroScene::controller_ == 2) {</div><div class="line">      <span class="comment">// setup mouse controller</span></div><div class="line">      <span class="keyword">auto</span> mouse = PS2Controller.<a class="code" href="classfabgl_1_1_p_s2_controller_a2248eef1cd0e3b15957c08d6094926b6.html#a2248eef1cd0e3b15957c08d6094926b6">mouse</a>();</div><div class="line">      mouse-&gt;<a name="a14"></a><a class="code" href="classfabgl_1_1_mouse_a47344d7eecf20504d7ea80020aaa0b73.html#a47344d7eecf20504d7ea80020aaa0b73">setSampleRate</a>(40);  <span class="comment">// reduce number of samples from mouse to reduce delays</span></div><div class="line">      mouse-&gt;setupAbsolutePositioner(getWidth() - player_-&gt;getWidth(), 0, <span class="keyword">false</span>); <span class="comment">// take advantage of mouse acceleration</span></div><div class="line">    }</div><div class="line"></div><div class="line">    showLives();</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> drawScore()</div><div class="line">  {</div><div class="line">    canvas.setPenColor(255, 255, 255);</div><div class="line">    canvas.drawTextFmt(2, 14, <span class="stringliteral">&quot;%05d&quot;</span>, score_);</div><div class="line">    <span class="keywordflow">if</span> (score_ &gt; hiScore_)</div><div class="line">      hiScore_ = score_;</div><div class="line">    canvas.setPenColor(255, 255, 255);</div><div class="line">    canvas.drawTextFmt(266, 14, <span class="stringliteral">&quot;%05d&quot;</span>, hiScore_);</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> moveEnemy(SISprite * enemy, <span class="keywordtype">int</span> x, <span class="keywordtype">int</span> y, <span class="keywordtype">bool</span> * touchSide)</div><div class="line">  {</div><div class="line">    <span class="keywordflow">if</span> (enemy-&gt;visible) {</div><div class="line">      <span class="keywordflow">if</span> (x &lt;= 0 || x &gt;= getWidth() - enemy-&gt;getWidth())</div><div class="line">        *touchSide = <span class="keyword">true</span>;</div><div class="line">      enemy-&gt;moveTo(x, y);</div><div class="line">      enemy-&gt;setFrame(enemy-&gt;getFrameIndex() ? 0 : 1);</div><div class="line">      updateSprite(enemy);</div><div class="line">      <span class="keywordflow">if</span> (y &gt;= PLAYER_Y) {</div><div class="line">        <span class="comment">// enemies reach earth!</span></div><div class="line">        gameState_ = GAMESTATE_ENDGAME;</div><div class="line">      }</div><div class="line">    }</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> gameOver()</div><div class="line">  {</div><div class="line">    <span class="comment">// disable enemies drawing, so text can be over them</span></div><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; ROWENEMIESCOUNT * 5; ++i)</div><div class="line">      enemies_[i].allowDraw = <span class="keyword">false</span>;</div><div class="line">    <span class="comment">// show game over</span></div><div class="line">    canvas.setPenColor(0, 255, 0);</div><div class="line">    canvas.setBrushColor(0, 0, 0);</div><div class="line">    canvas.fillRectangle(80, 60, 240, 130);</div><div class="line">    canvas.drawRectangle(80, 60, 240, 130);</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a class="code" href="displaycontroller_8h_aceea3df50e577272aa576027eede649d.html#aceea3df50e577272aa576027eede649d">DoubleWidth</a>(1));</div><div class="line">    canvas.setPenColor(255, 255, 255);</div><div class="line">    canvas.drawText(90, 80, <span class="stringliteral">&quot;GAME OVER&quot;</span>);</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a class="code" href="displaycontroller_8h_aceea3df50e577272aa576027eede649d.html#aceea3df50e577272aa576027eede649d">DoubleWidth</a>(0));</div><div class="line">    canvas.setPenColor(0, 255, 0);</div><div class="line">    <span class="keywordflow">if</span> (IntroScene::controller_ == 1)</div><div class="line">      canvas.drawText(110, 100, <span class="stringliteral">&quot;Press [SPACE]&quot;</span>);</div><div class="line">    <span class="keywordflow">else</span> <span class="keywordflow">if</span> (IntroScene::controller_ == 2)</div><div class="line">      canvas.drawText(93, 100, <span class="stringliteral">&quot;Click to continue&quot;</span>);</div><div class="line">    <span class="comment">// change state</span></div><div class="line">    gameState_ = GAMESTATE_GAMEOVER;</div><div class="line">    level_ = 1;</div><div class="line">    lives_ = 3;</div><div class="line">    score_ = 0;</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> levelChange()</div><div class="line">  {</div><div class="line">    ++level_;</div><div class="line">    <span class="comment">// show game over</span></div><div class="line">    canvas.setPenColor(0, 255, 0);</div><div class="line">    canvas.drawRectangle(80, 80, 240, 110);</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a class="code" href="displaycontroller_8h_aceea3df50e577272aa576027eede649d.html#aceea3df50e577272aa576027eede649d">DoubleWidth</a>(1));</div><div class="line">    canvas.drawTextFmt(105, 88, <span class="stringliteral">&quot;LEVEL %d&quot;</span>, level_);</div><div class="line">    canvas.setGlyphOptions(GlyphOptions().<a class="code" href="displaycontroller_8h_aceea3df50e577272aa576027eede649d.html#aceea3df50e577272aa576027eede649d">DoubleWidth</a>(0));</div><div class="line">    <span class="comment">// change state</span></div><div class="line">    gameState_  = GAMESTATE_LEVELCHANGED;</div><div class="line">    pauseStart_ = esp_timer_get_time();</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> update(<span class="keywordtype">int</span> updateCount)</div><div class="line">  {</div><div class="line">    <span class="keyword">auto</span> keyboard = PS2Controller.<a class="code" href="classfabgl_1_1_p_s2_controller_ab7bbbedef758e471e6eb693acfb17c33.html#ab7bbbedef758e471e6eb693acfb17c33">keyboard</a>();</div><div class="line">    <span class="keyword">auto</span> mouse    = PS2Controller.<a class="code" href="classfabgl_1_1_p_s2_controller_a2248eef1cd0e3b15957c08d6094926b6.html#a2248eef1cd0e3b15957c08d6094926b6">mouse</a>();</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (updateScore_) {</div><div class="line">      updateScore_ = <span class="keyword">false</span>;</div><div class="line">      drawScore();</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (gameState_ == GAMESTATE_PLAYING || gameState_ == GAMESTATE_PLAYERKILLED) {</div><div class="line"></div><div class="line">      <span class="comment">// move enemies and shoot</span></div><div class="line">      <span class="keywordflow">if</span> ((updateCount % max(3, 21 - level_ * 2)) == 0) {</div><div class="line">        <span class="comment">// handle enemy explosion</span></div><div class="line">        <span class="keywordflow">if</span> (lastHitEnemy_) {</div><div class="line">          lastHitEnemy_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">          lastHitEnemy_ = <span class="keyword">nullptr</span>;</div><div class="line">        }</div><div class="line">        <span class="comment">// handle enemies movement</span></div><div class="line">        enemiesX_ += (-1 * (enemiesDir_ &amp; 1) + (enemiesDir_ &gt;&gt; 1 &amp; 1)) * ENEMIES_STEP_X;</div><div class="line">        enemiesY_ += (enemiesDir_ &gt;&gt; 2 &amp; 1) * ENEMIES_STEP_Y;</div><div class="line">        <span class="keywordtype">bool</span> touchSide = <span class="keyword">false</span>;</div><div class="line">        <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; ROWENEMIESCOUNT; ++i) {</div><div class="line">          moveEnemy(&amp;enemiesR1_[i], enemiesX_ + i * ENEMIES_X_SPACE, enemiesY_ + 0 * ENEMIES_Y_SPACE, &amp;touchSide);</div><div class="line">          moveEnemy(&amp;enemiesR2_[i], enemiesX_ + i * ENEMIES_X_SPACE, enemiesY_ + 1 * ENEMIES_Y_SPACE, &amp;touchSide);</div><div class="line">          moveEnemy(&amp;enemiesR3_[i], enemiesX_ + i * ENEMIES_X_SPACE, enemiesY_ + 2 * ENEMIES_Y_SPACE, &amp;touchSide);</div><div class="line">          moveEnemy(&amp;enemiesR4_[i], enemiesX_ + i * ENEMIES_X_SPACE, enemiesY_ + 3 * ENEMIES_Y_SPACE, &amp;touchSide);</div><div class="line">          moveEnemy(&amp;enemiesR5_[i], enemiesX_ + i * ENEMIES_X_SPACE, enemiesY_ + 4 * ENEMIES_Y_SPACE, &amp;touchSide);</div><div class="line">        }</div><div class="line">        <span class="keywordflow">switch</span> (enemiesDir_) {</div><div class="line">          <span class="keywordflow">case</span> ENEMY_MOV_DOWN_BEFORE_LEFT:</div><div class="line">            enemiesDir_ = ENEMY_MOV_RIGHT;</div><div class="line">            <span class="keywordflow">break</span>;</div><div class="line">          <span class="keywordflow">case</span> ENEMY_MOV_DOWN_BEFORE_RIGHT:</div><div class="line">            enemiesDir_ = ENEMY_MOV_LEFT;</div><div class="line">            <span class="keywordflow">break</span>;</div><div class="line">          <span class="keywordflow">default</span>:</div><div class="line">            <span class="keywordflow">if</span> (touchSide)</div><div class="line">              enemiesDir_ = (enemiesDir_ == ENEMY_MOV_LEFT ? ENEMY_MOV_DOWN_BEFORE_LEFT : ENEMY_MOV_DOWN_BEFORE_RIGHT);</div><div class="line">            <span class="keywordflow">break</span>;</div><div class="line">        }</div><div class="line">        <span class="comment">// sound</span></div><div class="line">        ++enemiesSoundCount_;</div><div class="line">        soundGenerator.playSamples(invadersSoundSamples[enemiesSoundCount_ % 4], invadersSoundSamplesSize[enemiesSoundCount_ % 4]);</div><div class="line">        <span class="comment">// handle enemies fire generation</span></div><div class="line">        <span class="keywordflow">if</span> (!enemiesFire_-&gt;visible) {</div><div class="line">          <span class="keywordtype">int</span> shottingEnemy = random(enemiesAlive_);</div><div class="line">          <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0, a = 0; i &lt; ROWENEMIESCOUNT * 5; ++i) {</div><div class="line">            <span class="keywordflow">if</span> (enemies_[i].visible) {</div><div class="line">              <span class="keywordflow">if</span> (a == shottingEnemy) {</div><div class="line">                enemiesFire_-&gt;x = enemies_[i].x + enemies_[i].getWidth() / 2;</div><div class="line">                enemiesFire_-&gt;y = enemies_[i].y + enemies_[i].getHeight() / 2;</div><div class="line">                enemiesFire_-&gt;visible = <span class="keyword">true</span>;</div><div class="line">                <span class="keywordflow">break</span>;</div><div class="line">              }</div><div class="line">              ++a;</div><div class="line">            }</div><div class="line">          }</div><div class="line">        }</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="keywordflow">if</span> (gameState_ == GAMESTATE_PLAYERKILLED) {</div><div class="line">        <span class="comment">// animate player explosion or restart playing other lives</span></div><div class="line">        <span class="keywordflow">if</span> ((updateCount % 20) == 0) {</div><div class="line">          <span class="keywordflow">if</span> (player_-&gt;getFrameIndex() == 1)</div><div class="line">            player_-&gt;setFrame(2);</div><div class="line">          <span class="keywordflow">else</span> {</div><div class="line">            player_-&gt;setFrame(0);</div><div class="line">            gameState_ = GAMESTATE_PLAYING;</div><div class="line">          }</div><div class="line">        }</div><div class="line">      } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (IntroScene::controller_ == 1 &amp;&amp; playerVelX_ != 0) {</div><div class="line">        <span class="comment">// move player using Keyboard</span></div><div class="line">        player_-&gt;x += playerVelX_;</div><div class="line">        player_-&gt;x = iclamp(player_-&gt;x, 0, getWidth() - player_-&gt;getWidth());</div><div class="line">        updateSprite(player_);</div><div class="line">      } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (IntroScene::controller_ == 2 &amp;&amp; playerAbsX_ != -1) {</div><div class="line">        <span class="comment">// move player using Mouse</span></div><div class="line">        player_-&gt;x = playerAbsX_;</div><div class="line">        playerAbsX_ = -1;</div><div class="line">        updateSprite(player_);</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// move player fire</span></div><div class="line">      <span class="keywordflow">if</span> (playerFire_-&gt;visible) {</div><div class="line">        playerFire_-&gt;y -= 3;</div><div class="line">        <span class="keywordflow">if</span> (playerFire_-&gt;y &lt; ENEMIES_START_Y)</div><div class="line">          playerFire_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">          updateSpriteAndDetectCollisions(playerFire_);</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// move enemies fire</span></div><div class="line">      <span class="keywordflow">if</span> (enemiesFire_-&gt;visible) {</div><div class="line">        enemiesFire_-&gt;y += 2;</div><div class="line">        enemiesFire_-&gt;setFrame( enemiesFire_-&gt;getFrameIndex() ? 0 : 1 );</div><div class="line">        <span class="keywordflow">if</span> (enemiesFire_-&gt;y &gt; PLAYER_Y + player_-&gt;getHeight())</div><div class="line">          enemiesFire_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">          updateSpriteAndDetectCollisions(enemiesFire_);</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// move enemy mother ship</span></div><div class="line">      <span class="keywordflow">if</span> (enemyMother_-&gt;visible &amp;&amp; enemyMother_-&gt;getFrameIndex() == 0) {</div><div class="line">        enemyMother_-&gt;x -= 1;</div><div class="line">        <span class="keywordflow">if</span> (enemyMother_-&gt;x &lt; -enemyMother_-&gt;getWidth())</div><div class="line">          enemyMother_-&gt;visible = <span class="keyword">false</span>;</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">          updateSprite(enemyMother_);</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// start enemy mother ship</span></div><div class="line">      <span class="keywordflow">if</span> ((updateCount % 800) == 0) {</div><div class="line">        soundGenerator.playSamples(motherShipSoundSamples, <span class="keyword">sizeof</span>(motherShipSoundSamples), 100, 7000);</div><div class="line">        enemyMother_-&gt;x = getWidth();</div><div class="line">        enemyMother_-&gt;setFrame(0);</div><div class="line">        enemyMother_-&gt;visible = <span class="keyword">true</span>;</div><div class="line">      }</div><div class="line"></div><div class="line">      <span class="comment">// handle fire and movement from controller</span></div><div class="line">      <span class="keywordflow">if</span> (IntroScene::controller_ == 1) {</div><div class="line">        <span class="comment">// KEYBOARD controller</span></div><div class="line">        <span class="keywordflow">if</span> (keyboard-&gt;isVKDown(<a name="a15"></a><a class="code" href="group___enumerations_gad0e6e31d5953384be4ea987eb3923e02.html#ggad0e6e31d5953384be4ea987eb3923e02ad1093d0c4350abe99ccd39bd6717020d">fabgl::VK_LEFT</a>))</div><div class="line">          playerVelX_ = -1;</div><div class="line">        <span class="keywordflow">else</span> <span class="keywordflow">if</span> (keyboard-&gt;isVKDown(<a name="a16"></a><a class="code" href="group___enumerations_gad0e6e31d5953384be4ea987eb3923e02.html#ggad0e6e31d5953384be4ea987eb3923e02aea80fc6815468c273ef3674aa7eae7f1">fabgl::VK_RIGHT</a>))</div><div class="line">          playerVelX_ = +1;</div><div class="line">        <span class="keywordflow">else</span></div><div class="line">          playerVelX_ = 0;</div><div class="line">        <span class="keywordflow">if</span> (keyboard-&gt;isVKDown(<a class="code" href="group___enumerations_gad0e6e31d5953384be4ea987eb3923e02.html#ggad0e6e31d5953384be4ea987eb3923e02a3c7529306367d92950b980963dabe2b0">fabgl::VK_SPACE</a>) &amp;&amp; !playerFire_-&gt;visible)  <span class="comment">// player fire?</span></div><div class="line">          fire();</div><div class="line">      } <span class="keywordflow">else</span> <span class="keywordflow">if</span> (IntroScene::controller_ == 2) {</div><div class="line">        <span class="comment">// MOUSE controller</span></div><div class="line">        <span class="keywordflow">if</span> (mouse-&gt;deltaAvailable()) {</div><div class="line">          MouseDelta delta;</div><div class="line">          mouse-&gt;getNextDelta(&amp;delta);</div><div class="line">          mouse-&gt;updateAbsolutePosition(&amp;delta);</div><div class="line">          playerAbsX_ = mouse-&gt;status().X;</div><div class="line">          <span class="keywordflow">if</span> (delta.buttons.left &amp;&amp; !playerFire_-&gt;visible)    <span class="comment">// player fire?</span></div><div class="line">            fire();</div><div class="line">        }</div><div class="line">      }</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (gameState_ == GAMESTATE_ENDGAME)</div><div class="line">      gameOver();</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (gameState_ == GAMESTATE_LEVELCHANGING)</div><div class="line">      levelChange();</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (gameState_ == GAMESTATE_LEVELCHANGED &amp;&amp; esp_timer_get_time() &gt;= pauseStart_ + 2500000) {</div><div class="line">      stop(); <span class="comment">// restart from next level</span></div><div class="line">      DisplayController.<a name="a17"></a><a class="code" href="classfabgl_1_1_bitmapped_display_controller_ad968eec19f2e3663a5431b96894636df.html#ad968eec19f2e3663a5431b96894636df">removeSprites</a>();</div><div class="line">    }</div><div class="line"></div><div class="line">    <span class="keywordflow">if</span> (gameState_ == GAMESTATE_GAMEOVER) {</div><div class="line"></div><div class="line">      <span class="comment">// animate player burning</span></div><div class="line">      <span class="keywordflow">if</span> ((updateCount % 20) == 0)</div><div class="line">        player_-&gt;setFrame( player_-&gt;getFrameIndex() == 1 ? 2 : 1);</div><div class="line"></div><div class="line">      <span class="comment">// wait for SPACE or click from mouse</span></div><div class="line">      <span class="keywordflow">if</span> ((IntroScene::controller_ == 1 &amp;&amp; keyboard-&gt;isVKDown(<a class="code" href="group___enumerations_gad0e6e31d5953384be4ea987eb3923e02.html#ggad0e6e31d5953384be4ea987eb3923e02a3c7529306367d92950b980963dabe2b0">fabgl::VK_SPACE</a>)) ||</div><div class="line">          (IntroScene::controller_ == 2 &amp;&amp; mouse-&gt;deltaAvailable() &amp;&amp; mouse-&gt;getNextDelta(<span class="keyword">nullptr</span>, 0) &amp;&amp; mouse-&gt;status().buttons.left)) {</div><div class="line">        stop();</div><div class="line">        DisplayController.<a class="code" href="classfabgl_1_1_bitmapped_display_controller_ad968eec19f2e3663a5431b96894636df.html#ad968eec19f2e3663a5431b96894636df">removeSprites</a>();</div><div class="line">      }</div><div class="line"></div><div class="line">    }</div><div class="line"></div><div class="line">    DisplayController.<a name="a18"></a><a class="code" href="classfabgl_1_1_bitmapped_display_controller_aeb689cfc2364a4d66e3ac3368146c70d.html#aeb689cfc2364a4d66e3ac3368146c70d">refreshSprites</a>();</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// player shoots</span></div><div class="line">  <span class="keywordtype">void</span> fire()</div><div class="line">  {</div><div class="line">    playerFire_-&gt;moveTo(player_-&gt;x + 7, player_-&gt;y - 1)-&gt;visible = <span class="keyword">true</span>;</div><div class="line">    soundGenerator.playSamples(fireSoundSamples, <span class="keyword">sizeof</span>(fireSoundSamples));</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="comment">// shield has been damaged</span></div><div class="line">  <span class="keywordtype">void</span> damageShield(SISprite * shield, Point collisionPoint)</div><div class="line">  {</div><div class="line">    Bitmap * shieldBitmap = shield-&gt;getFrame();</div><div class="line">    <span class="keywordtype">int</span> x = collisionPoint.X - shield-&gt;x;</div><div class="line">    <span class="keywordtype">int</span> y = collisionPoint.Y - shield-&gt;y;</div><div class="line">    shieldBitmap-&gt;setPixel(x, y, 0);</div><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; 32; ++i) {</div><div class="line">      <span class="keywordtype">int</span> px = iclamp(x + random(-4, 5), 0, shield-&gt;getWidth() - 1);</div><div class="line">      <span class="keywordtype">int</span> py = iclamp(y + random(-4, 5), 0, shield-&gt;getHeight() - 1);</div><div class="line">      shieldBitmap-&gt;setPixel(px, py, 0);</div><div class="line">    }</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> showLives()</div><div class="line">  {</div><div class="line">    canvas.fillRectangle(1, 181, 100, 195);</div><div class="line">    canvas.setPenColor(<a class="code" href="group___enumerations_gab87bacfdad76e61b9412d7124be44c1c.html#ggab87bacfdad76e61b9412d7124be44c1cab548046646b36c12aa6ba841de500094">Color::White</a>);</div><div class="line">    canvas.drawTextFmt(5, 181, <span class="stringliteral">&quot;%d&quot;</span>, lives_);</div><div class="line">    <span class="keywordflow">for</span> (<span class="keywordtype">int</span> i = 0; i &lt; lives_; ++i)</div><div class="line">      canvas.drawBitmap(15 + i * (bmpPlayer.width + 5), 183, &amp;bmpPlayer);</div><div class="line">  }</div><div class="line"></div><div class="line">  <span class="keywordtype">void</span> collisionDetected(Sprite * spriteA, Sprite * spriteB, Point collisionPoint)</div><div class="line">  {</div><div class="line">    SISprite * sA = (SISprite*) spriteA;</div><div class="line">    SISprite * sB = (SISprite*) spriteB;</div><div class="line">    <span class="keywordflow">if</span> (!lastHitEnemy_ &amp;&amp; sA-&gt;type == TYPE_PLAYERFIRE &amp;&amp; sB-&gt;type == TYPE_ENEMY) {</div><div class="line">      <span class="comment">// player fire hits an enemy</span></div><div class="line">      soundGenerator.playSamples(shootSoundSamples, <span class="keyword">sizeof</span>(shootSoundSamples));</div><div class="line">      sA-&gt;visible = <span class="keyword">false</span>;</div><div class="line">      sB-&gt;setFrame(2);</div><div class="line">      lastHitEnemy_ = sB;</div><div class="line">      --enemiesAlive_;</div><div class="line">      score_ += sB-&gt;enemyPoints;</div><div class="line">      updateScore_ = <span class="keyword">true</span>;</div><div class="line">      <span class="keywordflow">if</span> (enemiesAlive_ == 0)</div><div class="line">        gameState_ = GAMESTATE_LEVELCHANGING;</div><div class="line">    }</div><div class="line">    <span class="keywordflow">if</span> (sB-&gt;type == TYPE_SHIELD) {</div><div class="line">      <span class="comment">// something hits a shield</span></div><div class="line">      sA-&gt;visible = <span class="keyword">false</span>;</div><div class="line">      damageShield(sB, collisionPoint);</div><div class="line">      sB-&gt;allowDraw = <span class="keyword">true</span>;</div><div class="line">    }</div><div class="line">    <span class="keywordflow">if</span> (gameState_ == GAMESTATE_PLAYING &amp;&amp; sA-&gt;type == TYPE_ENEMIESFIRE &amp;&amp; sB-&gt;type == TYPE_PLAYER) {</div><div class="line">      <span class="comment">// enemies fire hits player</span></div><div class="line">      soundGenerator.playSamples(explosionSoundSamples, <span class="keyword">sizeof</span>(explosionSoundSamples));</div><div class="line">      --lives_;</div><div class="line">      gameState_ = lives_ ? GAMESTATE_PLAYERKILLED : GAMESTATE_ENDGAME;</div><div class="line">      player_-&gt;setFrame(1);</div><div class="line">      showLives();</div><div class="line">    }</div><div class="line">    <span class="keywordflow">if</span> (sB-&gt;type == TYPE_ENEMYMOTHER) {</div><div class="line">      <span class="comment">// player fire hits enemy mother ship</span></div><div class="line">      soundGenerator.playSamples(mothershipexplosionSoundSamples, <span class="keyword">sizeof</span>(mothershipexplosionSoundSamples));</div><div class="line">      sA-&gt;visible = <span class="keyword">false</span>;</div><div class="line">      sB-&gt;setFrame(1);</div><div class="line">      lastHitEnemy_ = sB;</div><div class="line">      score_ += sB-&gt;enemyPoints;</div><div class="line">      updateScore_ = <span class="keyword">true</span>;</div><div class="line">    }</div><div class="line">  }</div><div class="line"></div><div class="line">};</div><div class="line"></div><div class="line"><span class="keywordtype">int</span> GameScene::hiScore_ = 0;</div><div class="line"><span class="keywordtype">int</span> GameScene::level_   = 1;</div><div class="line"><span class="keywordtype">int</span> GameScene::lives_   = 3;</div><div class="line"><span class="keywordtype">int</span> GameScene::score_   = 0;</div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">void</span> setup()</div><div class="line">{</div><div class="line">  PS2Controller.<a name="a19"></a><a class="code" href="classfabgl_1_1_p_s2_controller_ab8520612804a921ad834b41214a99c09.html#ab8520612804a921ad834b41214a99c09">begin</a>(PS2Preset::KeyboardPort0_MousePort1, KbdMode::GenerateVirtualKeys);</div><div class="line"></div><div class="line">  DisplayController.begin();</div><div class="line">  DisplayController.<a name="a20"></a>setResolution(VGA_320x200_75Hz);</div><div class="line"></div><div class="line">  <span class="comment">// adjust this to center screen in your monitor</span></div><div class="line">  <span class="comment">//DisplayController.moveScreen(20, -2);</span></div><div class="line">}</div><div class="line"></div><div class="line"></div><div class="line"><span class="keywordtype">void</span> loop()</div><div class="line">{</div><div class="line">  <span class="keywordflow">if</span> (GameScene::level_ == 1) {</div><div class="line">    IntroScene introScene;</div><div class="line">    introScene.start();</div><div class="line">  }</div><div class="line">  GameScene gameScene;</div><div class="line">  gameScene.start();</div><div class="line">}</div></div><!-- fragment --> </div><!-- contents -->
</div><!-- doc-content -->
<!-- start footer part -->
<div id="nav-path" class="navpath"><!-- id is needed for treeview function! -->
  <ul>
    <li class="footer">Generated on Wed Dec 9 2020 16:48:29 for FabGL by
    <a href="http://www.doxygen.org/index.html">
    <img class="footer" src="doxygen.png" alt="doxygen"/></a> 1.8.14 </li>
  </ul>
</div>
</body>
</html>
